package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.Category;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.*;
/**
 * <h3>leyou-project</h3>
 * <p></p>
 *
 * @author : hhw
 * @date : 2020-05-28 12:06
 **/
@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SpuDetailService spuDetailService;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Override
    public PageDTO<SpuDTO> queryPage(Long brandId, Long categoryId, Long id, Long page, Long rows, Boolean saleable) {
        /**
         * 1.查数据
         * 2.分页,封装置PageDto
         */
        //健壮性
        page = Math.max(1, Math.min(page, 100));
        rows = Math.max(5, rows);
        Spu spu = new Spu();
        spu.setBrandId(brandId);
        spu.setCid3(categoryId);
        spu.setId(id);
        spu.setSaleable(saleable);

        QueryWrapper<Spu> wrapper = new QueryWrapper<>(spu);
        IPage<Spu> spuPage = page(new Page<Spu>(page, rows), wrapper);
        List<Spu> records = spuPage.getRecords();
        if (CollectionUtils.isEmpty(records)){
            throw  new LyException(400, "商品不存在");
        }
        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(records);
        spuDTOS.forEach(spuDTO -> handleCategoryNameAndBrandName(spuDTO));
        long total = spuPage.getTotal();
        long pages = spuPage.getPages();
        PageDTO<SpuDTO> pageDTO = new PageDTO<>(total, pages, spuDTOS);
        return pageDTO;
    }

    @Override
    @Transactional
    public void saveGoods(SpuDTO spuDTO) {
        /**
         * 1.获取sku和spudetail表
         * 2.保存他们
         */
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        List<Sku> skuList = spuDTO.getSkus().stream().map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.toList());
        Spu spu = spuDTO.toEntity(Spu.class);

        spu.setSaleable(false);
        boolean flag = save(spu);
        if (!flag) {
            throw new LyException(500, "保存商品spu失败");
        }

        spuDetail.setSpuId(spu.getId());
        flag = spuDetailService.save(spuDetail);
        if (!flag) {
            throw new LyException(500, "保存商品spudetail失败");
        }

        skuList.forEach(sku -> {sku.setSaleable(false); sku.setSpuId(spu.getId());});
        flag = skuService.saveBatch(skuList);
        if (!flag) {
            throw new LyException(500, "保存商品sku失败");
        }
    }

    @Override
    @Transactional
    public void updateSaleable(Long id, Boolean saleable) {
        /**
         * 1.修改spu商品的上下架信息
         * 2.获取spuid对应的sku列表
         * 3.修改sku商品的上下架信息
         */
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean flag = updateById(spu);
        if (!flag) {
            throw new LyException(500, "更新上下架信息失败");
        }
     /*   List<Sku> skuList = skuService.lambdaQuery().eq(Sku::getSpuId, id).list();
        skuList.forEach(sku -> sku.setSaleable(saleable));
        skuService.updateBatchById(skuList);*/
        flag = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!flag) {
            throw new LyException(500, "更新sku上下架信息失败");
        }
        // 发送消息

        String routingKey = saleable ? RoutingKeyConstants.ITEM_UP_KEY : RoutingKeyConstants.ITEM_DOWN_KEY;
        rabbitTemplate.convertAndSend(ExchangeConstants.ITEM_EXCHANGE_NAME, routingKey, id);
    }

    @Override
    public SpuDTO querySpuDetailAndSkuById(Long id) {
        /**
         * 1.查询spu
         * 2.根据spuid查询spudetail
         * 3.根据spuid查询skus
         * 4.封装分类名称和品牌名称
         */
        SpuDTO spuDTO = new SpuDTO(getById(id));
        spuDTO.setSpuDetail(new SpuDetailDTO(spuDetailService.getOne(new QueryWrapper<SpuDetail>().eq("spu_id", id))));
        spuDTO.setSkus(SkuDTO.convertEntityList(skuService.lambdaQuery().eq(Sku::getSpuId, id).list()));
        handleCategoryNameAndBrandName(spuDTO);
        return spuDTO;
    }

    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        /**
         * 1.是否包含spu信息
         * 2.是否包含spudetail信息
         * 3.是否包含sku信息
         *      -是否包含saleable字段
         *          -是, 删除字段
         *          -否, 新增或修改
         *              -有id  修改
         *              -无id  新增
         */
        if (spuDTO.getId() != null) {
            boolean flag = updateById(spuDTO.toEntity(Spu.class));
            if (!flag) {
                throw new LyException(500, "更新spu失败");
            }
        }
        SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
        if (spuDetail != null) {
            boolean flag = spuDetailService.updateById(spuDetail.toEntity(SpuDetail.class));
            if (!flag) {
                throw new LyException(500, "更新spu失败");
            }
        }

        //没有sku相关信息
        List<SkuDTO> skus = spuDTO.getSkus();
        if (CollectionUtils.isEmpty(skus)) {
            return ;
        }
        //将是否有saleable作为条件分组
        Map<Boolean, List<Sku>> skuMap = skus.stream().map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));

        List<Sku> hasSaleable = skuMap.get(false);
        //删除有saleable字段的sku信息
        if (!CollectionUtils.isEmpty(hasSaleable)) {
            boolean flag = skuService.removeByIds(hasSaleable.stream().map(sku -> sku.getId()).collect(Collectors.toList()));
            if (!flag) {
                throw new LyException(500, "删除sku失败");
            }
        }
        List<Sku> hasNotSaleable = skuMap.get(true);
        if (!CollectionUtils.isEmpty(hasNotSaleable)) {
            boolean flag = skuService.saveOrUpdateBatch(hasNotSaleable);
            if (!flag) {
                throw new LyException(500, "更新或新增sku失败");
            }
        }
    }

    void handleCategoryNameAndBrandName(SpuDTO spuDTO){
        spuDTO.setBrandName(brandService.getById(spuDTO.getBrandId()).getName());
        String categoryName = categoryService.listByIds(spuDTO.getCategoryIds())
                .stream()
                .map(Category::getName)
                .collect(Collectors.joining("/"));
        spuDTO.setCategoryName(categoryName);
    }
}
